//-----------------------------------------------------------------------------
// Bend2D - Physics Engine
// Roberto Bender <beto.bender@gmail.com>
// Description: 
// Date: 14/03/2010
//-----------------------------------------------------------------------------
#include "line.h"
using namespace bend2d;

Line::Line() :
    m_Direction(eUnknown),
    m_Changed(true)
{
}

Line::Line(const Point& from, const Point& to) :
    m_From(from),
    m_To(to),
    m_Direction(eUnknown),
    m_Changed(true)
{
}

Line::Line(double xfrom, double yfrom, double xto, double yto) :
    m_From(xfrom, yfrom),
    m_To(xto, yto),
    m_Direction(eUnknown),
    m_Changed(true)
{
}

const Point& Line::GetFrom() const
{
    return m_From;
}

const Point& Line::GetTo() const
{
    return m_To;
}

void Line::SetFrom(const Point& point)
{
    m_From = point;
    m_Changed = true;
    m_Direction = eUnknown;
}

void Line::SetTo(const Point& point)
{
    m_To = point;
    m_Changed = true;
    m_Direction = eUnknown;
}

void Line::CalculateVariables()
{
    if(m_Changed == false)
        return;

    m_Alpha = GetTo().GetY()-GetFrom().GetY();
    m_Beta = GetFrom().GetX()-GetTo().GetX();
    m_Gamma = m_Alpha * GetFrom().GetX() + m_Beta * GetFrom().GetY();
    m_Low.SetXY((m_From.GetX() < m_To.GetX())?m_From.GetX():m_To.GetX(), (m_From.GetY() < m_To.GetY())?m_From.GetY():m_To.GetY());
    m_High.SetXY((m_From.GetX() >= m_To.GetX())?m_From.GetX():m_To.GetX(), (m_From.GetY() >= m_To.GetY())?m_From.GetY():m_To.GetY());
    
    m_Changed = false;
}

double Line::CalculateX(double y) const
{
    // C = A*x + B*y
    // - A*x = B*y - C
    // x = (B*y - C) / A
    return (m_Beta*y - m_Gamma) / m_Alpha;
}

double Line::CalculateY(double x) const
{
    // C = A*x + B*y
    // - B*y = A*x - C
    // y = (A*x - C) / B
    return (m_Alpha*x - m_Gamma) / m_Beta;
}

Line::LineDirection Line::GetLineDirection()
{
    if(m_Direction != eUnknown) 
        return m_Direction;

    if(m_From.GetX() <= m_To.GetX())
        if(m_From.GetY() <= m_To.GetY()) 
            m_Direction = eTopRight;
        else
            m_Direction = eBottomRight;
    else
        if(m_From.GetY() <= m_To.GetY()) 
            m_Direction = eTopLeft;
        else
            m_Direction = eTopRight;

    return m_Direction;
}

double Line::GetAlpha() const
{
    return m_Alpha;
}

double Line::GetBeta() const
{
    return m_Beta;
}

double Line::GetGamma() const
{
    return m_Gamma;
}

double Line::GetLowY() const
{
    return m_Low.GetY();
}

double Line::GetHighY() const
{
    return m_High.GetY();
}

double Line::GetLowX() const
{
    return m_Low.GetX();
}

double Line::GetHighX() const
{
    return m_High.GetX();
}

